package com.hb.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;

import javax.servlet.ServletRegistration;

/**
 * 1、有多种方式来配置 DispatcherServlet，与之类似，启用 SpringMVC 组件的方法也不仅一种。以前，Spring 是使用 XML 进行配置的，你可以使用 <mvc:annotation-driven />
 * 启用注解驱动的 SpringMVC。
 * 2、如果没有配置视图解析器。Spring 默认会使用 BeanNameViewResolver，这个视图解析器会查找 ID 与视图名称匹配的 bean，并且查找的 bean 要实现 View 接口（这个 bean 其实就是视图对象），
 * 它以这样的方式来解析视图；如果没有启用组件扫描，那么 Spring 只能找到显式声明在配置类中的控制器；如果只使用 @Configuration 和 @EnableWebMvc 这两个注解标注的配置类时，这个配置类属于
 * 最小的 SpringMVC 配置，此时 DispatcherServlet 会映射为应用的默认 Servlet，所以它会处理所有的请求，包括对静态资源的请求，如图片和样式表（在大多数情况下，这可能并不是你想要的效果）。
 */
@Configuration
@EnableWebMvc   // 启用 SpringMVC
@ComponentScan(basePackageClasses = com.hb.web.ComponentScanFlagClass.class)    // 启用组件扫描
public class WebConfig extends WebMvcConfigurerAdapter {
    /**
     * 测试发现当在 Tile 的定义文件中定义要使用的 jsp 时，可以不用配置 InternalResourceViewResolver 也能正常显示 jsp 页面
     * @return
     */
    @Bean
    public ViewResolver jspViewResolver() {
        // 配置 JSP 视图解析器
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        // 当 InternalResourceViewResolver 和 TilesViewResolver 一起使用时 InternalResourceViewResolver 的 Order 属性需要设置得比 TilesViewResolver 大，
        // 也就是 TilesViewResolver 的注册顺序要在 InternalResourceViewResolver 前面，不然 Tiles 布局会不起作用。
        resolver.setOrder(1);
        return resolver;
    }

    /**
     * 配置静态资源的处理
     * 我们要求 DispatcherServlet 将对静态资源的请求转发到 Servlet 容器中默认的 Servlet 上，而不是使用 DispatcherServlet 本身来处理此类请求。
     * @param configurer
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        // 通过启用默认 Servlet 处理配置后 DispatcherServlet 将对静态资源的请求转发到 Servlet 容器中默认的 Servlet 上，而不是使用 DispatcherServlet 本身来处理此类请求
        configurer.enable();
    }

    @Bean
    public TilesConfigurer tilesConfigurer() {
        TilesConfigurer tiles = new TilesConfigurer();
        // 当配置 TilesConfigurer 的时候，所要设置的最重要的属性就是 definitions。这个属性接受一个 String 类型的数组，其中每
        // 个条目都指定一个 Tile 定义的 XML 文件
        tiles.setDefinitions(new String[] {
                "/WEB-INF/layout/tiles.xml",
                // 我们还可以指定多个 Tile 定义文件，甚至能够在路径位置上使用通配符，这里我们使用了 Ant 风格的通配符（**），所以 TilesConfigurer
                // 会遍历 “WEB-INF/views” 的所有子目录来查找 Tile 定义
                "/WEB-INF/views/**/tiles.xml"
        });
        // 启用刷新功能
        tiles.setCheckRefresh(true);
        return tiles;
    }

    @Bean
    public ViewResolver viewResolver() {
        TilesViewResolver resolver = new TilesViewResolver();
        resolver.setOrder(0);
        return resolver;
    }
}
